home *** CD-ROM | disk | FTP | other *** search
/ Hot Super Models / Hot Super Models.iso / unix / x11 / xv2r1.tar / xv2r1 / extensions / xv / server / xvmain.c < prev    next >
C/C++ Source or Header  |  1991-09-05  |  25KB  |  1,155 lines

  1. /***********************************************************
  2. Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24. /*
  25. ** File: 
  26. **
  27. **   xvmain.c --- Xv server extension main device independent module.
  28. **   
  29. ** Author: 
  30. **
  31. **   David Carver (Digital Workstation Engineering/Project Athena)
  32. **
  33. ** Revisions:
  34. **
  35. **   04.09.91 Carver
  36. **     - change: stop video always generates an event even when video
  37. **       wasn't active
  38. **
  39. **   29.08.91 Carver
  40. **     - change: unrealizing windows no longer preempts video
  41. **
  42. **   11.06.91 Carver
  43. **     - changed SetPortControl to SetPortAttribute
  44. **     - changed GetPortControl to GetPortAttribute
  45. **     - changed QueryBestSize
  46. **
  47. **   28.05.91 Carver
  48. **     - fixed Put and Get requests to not preempt operations to same drawable
  49. **
  50. **   15.05.91 Carver
  51. **     - version 2.0 upgrade
  52. **
  53. **   19.03.91 Carver
  54. **     - fixed Put and Get requests to honor grabbed ports.
  55. **     - fixed Video requests to update di structure with new drawable, and
  56. **       client after calling ddx.
  57. **
  58. **   24.01.91 Carver
  59. **     - version 1.4 upgrade
  60. **       
  61. ** Notes:
  62. **
  63. **   Port structures reference client structures in a two different
  64. **   ways: when grabs, or video is active.  Each reference is encoded
  65. **   as fake client resources and thus when the client is goes away so
  66. **   does the reference (it is zeroed).  No other action is taken, so
  67. **   video doesn't necessarily stop.  It probably will as a result of
  68. **   other resources going away, but if a client starts video using
  69. **   none of its own resources, then the video will continue to play
  70. **   after the client disappears.
  71. **
  72. **
  73. */
  74.  
  75. #include <stdio.h>
  76.  
  77. #include "X.h"
  78. #include "Xproto.h"
  79. #include "misc.h"
  80. #include "os.h"
  81. #include "scrnintstr.h"
  82. #include "windowstr.h"
  83. #include "pixmapstr.h"
  84. #include "gc.h"
  85. #include "extnsionst.h"
  86. #include "dixstruct.h"
  87. #include "resource.h"
  88. #include "opaque.h"
  89. #include "input.h"
  90.  
  91. #define GLOBAL
  92.  
  93. #include "Xv.h"
  94. #include "Xvproto.h"
  95. #include "xvdix.h"
  96.  
  97. /* EXTERNAL */
  98.  
  99. extern Atom MakeAtom();
  100. extern WindowPtr *WindowTable;
  101. extern XID clientErrorValue;
  102. extern void (* EventSwapVector[128])();
  103.  
  104. static void WriteSwappedVideoNotifyEvent();
  105. static void WriteSwappedPortNotifyEvent();
  106. static Bool CreateResourceTypes();
  107.  
  108. static int lastScreenWithAdaptors = 0;
  109.  
  110. /*
  111. ** XvExtensionInit
  112. **
  113. **
  114. */
  115.  
  116. void 
  117. XvExtensionInit()
  118. {
  119.   int ii;
  120.   register ExtensionEntry *extEntry;
  121.  
  122.   /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN
  123.      INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */
  124.  
  125.   if (XvScreenGeneration != serverGeneration)
  126.     {
  127.       if (!CreateResourceTypes())
  128.     {
  129.       ErrorF("XvExtensionInit: Unable to allocate resource types\n");
  130.       return;
  131.     }
  132.       XvScreenIndex = AllocateScreenPrivateIndex ();
  133.       if (XvScreenIndex < 0)
  134.     {
  135.       ErrorF("XvExtensionInit: Unable to allocate screen private index\n");
  136.       return;
  137.     }
  138.  
  139.       XvScreenGeneration = serverGeneration;
  140.     }
  141.  
  142.   /* ITS A LITTLE HARD TO UNDERSTAND WHAT THIS DOES, BUT ESSENTIALLY I WANT 
  143.      ALL SCREEN THAT HAVE ADAPTORS TO HAVE A VALID DEVPRIVATE POINTER AND ANY 
  144.      THAT DON'T TO HAVE NULL DEVPRIVATE POINTERS; THIS WAY I DON'T HAVE TO 
  145.      CALL A SPECIAL XV SCREEN INITIALIZE FOR SCREENS WITHOUT ADAPTORS; THERE
  146.      SHOULD BE AN EASIER WAY TO DO THIS, BUT main.c DOESN'T INITIALIZE THE 
  147.      DEVPRIVATE POINTERS FOR A NEWLY CREATED SCREEN, NOR ARE THEY INITIALIZED
  148.      WHEN A NEW SCREEN PRIVATE INDEX IS ALLOCATED */
  149.  
  150.   for (ii=lastScreenWithAdaptors; ii<screenInfo.numScreens; ii++)
  151.     screenInfo.screens[ii]->devPrivates[XvScreenIndex].ptr = (pointer)NULL;
  152.   lastScreenWithAdaptors = screenInfo.numScreens;
  153.  
  154.   if (XvExtensionGeneration != serverGeneration)
  155.     {
  156.       XvExtensionGeneration = serverGeneration;
  157.  
  158.       extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors, 
  159.                   ProcXvDispatch, SProcXvDispatch,
  160.                   XvResetProc, StandardMinorOpcode);
  161.       if (!extEntry) 
  162.     {
  163.       FatalError("XvExtensionInit: AddExtensions failed\n");
  164.     }
  165.  
  166.       XvReqCode = extEntry->base;
  167.       XvEventBase = extEntry->eventBase;
  168.       XvErrorBase = extEntry->errorBase;
  169.  
  170.       EventSwapVector[XvEventBase+XvVideoNotify] = 
  171.     WriteSwappedVideoNotifyEvent;
  172.       EventSwapVector[XvEventBase+XvPortNotify] = 
  173.     WriteSwappedPortNotifyEvent;
  174.  
  175.       (void)MakeAtom(XvName, strlen(XvName), xTrue);
  176.  
  177.     }
  178. }
  179.  
  180. static Bool
  181. CreateResourceTypes()
  182.  
  183. {
  184.   
  185.   if (XvResourceGeneration == serverGeneration) return TRUE;
  186.  
  187.   XvResourceGeneration = serverGeneration;
  188.  
  189.   if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort)))
  190.     {
  191.       ErrorF("CreateResourceTypes: failed to allocate port resource.\n");
  192.       return FALSE;
  193.     }
  194.   
  195.   if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab)))
  196.     {
  197.       ErrorF("CreateResourceTypes: failed to allocate grab resource.\n");
  198.       return FALSE;
  199.     }
  200.   
  201.   if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding)))
  202.     {
  203.       ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n");
  204.       return FALSE;
  205.     }
  206.   
  207.   if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify)))
  208.     {
  209.       ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n");
  210.       return FALSE;
  211.     }
  212.   
  213.   if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList)))
  214.     {
  215.       ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n");
  216.       return FALSE;
  217.     }
  218.  
  219.   if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify)))
  220.     {
  221.       ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n");
  222.       return FALSE;
  223.     }
  224.  
  225.   return TRUE;
  226.  
  227. }
  228.  
  229. int
  230. XvScreenInit(pScreen)
  231. ScreenPtr pScreen;
  232.  
  233. {
  234.  
  235.   int ii;
  236.   XvScreenPtr pxvs;
  237.  
  238.   if (XvScreenGeneration != serverGeneration)
  239.     {
  240.       if (!CreateResourceTypes())
  241.     {
  242.       ErrorF("XvScreenInit: Unable to allocate resource types\n");
  243.       return BadAlloc;
  244.     }
  245.       XvScreenIndex = AllocateScreenPrivateIndex ();
  246.       if (XvScreenIndex < 0)
  247.     {
  248.       ErrorF("XvScreenInit: Unable to allocate screen private index\n");
  249.       return BadAlloc;
  250.     }
  251.       XvScreenGeneration = serverGeneration; 
  252.     }
  253.  
  254.   /* ITS A LITTLE HARD TO UNDERSTAND WHAT THIS DOES, BUT ESSENTIALLY I WANT 
  255.      ALL SCREEN THAT HAVE ADAPTORS TO HAVE A VALID DEVPRIVATE POINTER AND ANY 
  256.      THAT DON'T TO HAVE NULL DEVPRIVATE POINTERS; THIS WAY I DON'T HAVE TO 
  257.      CALL A SPECIAL XV SCREEN INITIALIZE FOR SCREENS WITHOUT ADAPTORS; THERE
  258.      SHOULD BE AN EASIER WAY TO DO THIS, BUT main.c DOESN'T INITIALIZE THE 
  259.      DEVPRIVATE POINTERS FOR A NEWLY CREATED SCREEN, NOR ARE THEY INITIALIZED
  260.      WHEN A NEW SCREEN PRIVATE INDEX IS ALLOCATED */
  261.  
  262.   for (ii=lastScreenWithAdaptors; ii<screenInfo.numScreens; ii++)
  263.     screenInfo.screens[ii]->devPrivates[XvScreenIndex].ptr = (pointer)NULL;
  264.   lastScreenWithAdaptors = screenInfo.numScreens;
  265.  
  266.   if (pScreen->devPrivates[XvScreenIndex].ptr)
  267.     {
  268.       ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n");
  269.     }
  270.  
  271.   /* ALLOCATE SCREEN PRIVATE RECORD */
  272.   
  273.   pxvs = (XvScreenPtr) xalloc (sizeof (XvScreenRec));
  274.   if (!pxvs)
  275.     {
  276.       ErrorF("XvScreenInit: Unable to allocate screen private structure\n");
  277.       return BadAlloc;
  278.     }
  279.   
  280.   pxvs->DestroyPixmap = pScreen->DestroyPixmap;
  281.   pxvs->DestroyWindow = pScreen->DestroyWindow;
  282.   pxvs->CloseScreen = pScreen->CloseScreen;
  283.   
  284.   pScreen->DestroyPixmap = XvDestroyPixmap;
  285.   pScreen->DestroyWindow = XvDestroyWindow;
  286.   pScreen->CloseScreen = XvCloseScreen;
  287.  
  288.   pScreen->devPrivates[XvScreenIndex].ptr = (pointer)pxvs;
  289.  
  290.   return Success;
  291.  
  292. }
  293.  
  294. Bool
  295. XvCloseScreen(ii, pScreen)
  296. int ii;
  297. ScreenPtr pScreen;
  298.  
  299. {
  300.  
  301.   XvScreenPtr pxvs;
  302.  
  303.   pxvs = (XvScreenPtr) pScreen->devPrivates[XvScreenIndex].ptr;
  304.  
  305.   pScreen->DestroyPixmap = pxvs->DestroyPixmap;
  306.   pScreen->DestroyWindow = pxvs->DestroyWindow;
  307.   pScreen->CloseScreen = pxvs->CloseScreen;
  308.  
  309.   (* pxvs->ddCloseScreen)(ii, pScreen);
  310.  
  311.   xfree(pxvs);
  312.  
  313.   pScreen->devPrivates[XvScreenIndex].ptr = (pointer)NULL;
  314.  
  315.   return (*pScreen->CloseScreen)(ii, pScreen);
  316.  
  317. }
  318.  
  319. void
  320. XvResetProc()
  321. {
  322.   lastScreenWithAdaptors = 0;
  323. }
  324.  
  325. Bool
  326. XvDestroyPixmap(pPix)
  327.  
  328. PixmapPtr pPix;
  329.  
  330. {
  331.   Bool status;
  332.   ScreenPtr pScreen;
  333.   XvScreenPtr pxvs;
  334.   XvAdaptorPtr pa;
  335.   int na;
  336.   XvPortPtr pp;
  337.   int np;
  338.  
  339.   pScreen = pPix->drawable.pScreen;
  340.  
  341.   SCREEN_PROLOGUE(pScreen, DestroyPixmap);
  342.  
  343.   pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr;
  344.  
  345.   /* CHECK TO SEE IF THIS PORT IS IN USE */
  346.  
  347.   pa = pxvs->pAdaptors;
  348.   na = pxvs->nAdaptors;
  349.   while (na--)
  350.     {
  351.       np = pa->nPorts;
  352.       pp = pa->pPorts;
  353.  
  354.       while (np--)
  355.     {
  356.       if (pp->pDraw == (DrawablePtr)pPix)
  357.         {
  358.           XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
  359.  
  360.           (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, 
  361.                           pp->pDraw);
  362.  
  363.           pp->pDraw = (DrawablePtr)NULL;
  364.           pp->client = (ClientPtr)NULL;
  365.           pp->time = currentTime;
  366.         }
  367.       pp++;
  368.     }
  369.       pa++;
  370.     }
  371.   
  372.   status = (* pScreen->DestroyPixmap)(pPix);
  373.  
  374.   SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap);
  375.  
  376.   return status;
  377.  
  378. }
  379.  
  380. Bool
  381. XvDestroyWindow(pWin)
  382.  
  383. WindowPtr pWin;
  384.  
  385. {
  386.   Bool status;
  387.   ScreenPtr pScreen;
  388.   XvScreenPtr pxvs;
  389.   XvAdaptorPtr pa;
  390.   int na;
  391.   XvPortPtr pp;
  392.   int np;
  393.  
  394.   pScreen = pWin->drawable.pScreen;
  395.  
  396.   SCREEN_PROLOGUE(pScreen, DestroyWindow);
  397.  
  398.   pxvs = (XvScreenPtr)pScreen->devPrivates[XvScreenIndex].ptr;
  399.  
  400.   /* CHECK TO SEE IF THIS PORT IS IN USE */
  401.  
  402.   pa = pxvs->pAdaptors;
  403.   na = pxvs->nAdaptors;
  404.   while (na--)
  405.     {
  406.       np = pa->nPorts;
  407.       pp = pa->pPorts;
  408.  
  409.       while (np--)
  410.     {
  411.       if (pp->pDraw == (DrawablePtr)pWin)
  412.         {
  413.           XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted);
  414.  
  415.           (void)(* pp->pAdaptor->ddStopVideo)((ClientPtr)NULL, pp, 
  416.                           pp->pDraw);
  417.  
  418.           pp->pDraw = (DrawablePtr)NULL;
  419.           pp->client = (ClientPtr)NULL;
  420.           pp->time = currentTime;
  421.         }
  422.       pp++;
  423.     }
  424.       pa++;
  425.     }
  426.   
  427.   status = (* pScreen->DestroyWindow)(pWin);
  428.  
  429.   SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow);
  430.  
  431.   return status;
  432.  
  433. }
  434.  
  435. /* The XvdiVideoStopped procedure is a hook for the device dependent layer.
  436.    It provides a way for the dd layer to inform the di layer that video has
  437.    stopped in a port for reasons that the di layer had no control over; note
  438.    that it doesn't call back into the dd layer */
  439.  
  440. int
  441. XvdiVideoStopped(pPort, reason)
  442.  
  443. XvPortPtr pPort;
  444. int reason;
  445.  
  446. {
  447.   
  448.   /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
  449.  
  450.   if (!pPort->pDraw) return Success;
  451.  
  452.   XvdiSendVideoNotify(pPort, pPort->pDraw, reason);
  453.  
  454.   pPort->pDraw = (DrawablePtr)NULL;
  455.   pPort->client = (ClientPtr)NULL;
  456.   pPort->time = currentTime;
  457.  
  458.   return Success;
  459.  
  460. }
  461.  
  462. int 
  463. XvdiDestroyPort(pPort)
  464. XvPortPtr pPort;
  465. {
  466.   return (* pPort->pAdaptor->ddFreePort)(pPort);
  467. }
  468.  
  469. int
  470. XvdiDestroyGrab(pGrab)
  471. XvGrabPtr pGrab;
  472. {
  473.   pGrab->client = (ClientPtr)NULL;
  474. }
  475.  
  476. int
  477. XvdiDestroyVideoNotify(pn)
  478. XvVideoNotifyPtr pn;
  479.  
  480. {
  481.   /* JUST CLEAR OUT THE client POINTER FIELD */
  482.  
  483.   pn->client = (ClientPtr)NULL;
  484. }
  485.  
  486. int
  487. XvdiDestroyPortNotify(pn)
  488. XvPortNotifyPtr pn;
  489.  
  490. {
  491.   /* JUST CLEAR OUT THE client POINTER FIELD */
  492.  
  493.   pn->client = (ClientPtr)NULL;
  494. }
  495.  
  496. int
  497. XvdiDestroyVideoNotifyList(pn)
  498. XvVideoNotifyPtr pn;
  499.  
  500. {
  501.   XvVideoNotifyPtr npn,cpn;
  502.  
  503.   /* ACTUALLY DESTROY THE NOTITY LIST */
  504.  
  505.   cpn = pn;
  506.  
  507.   while (cpn)
  508.     {
  509.       npn = cpn->next;
  510.       if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify);
  511.       xfree(cpn);
  512.       cpn = npn;
  513.     }
  514. }
  515.  
  516. int
  517. XvdiDestroyEncoding()
  518. {
  519. }
  520.  
  521. int
  522. XvdiSendVideoNotify(pPort, pDraw, reason)
  523.  
  524. XvPortPtr pPort;
  525. DrawablePtr pDraw;
  526. int reason;
  527.  
  528. {
  529.   xvEvent event;
  530.   XvVideoNotifyPtr pn;
  531.  
  532.   pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList);
  533.  
  534.   while (pn) 
  535.     {
  536.       if (pn->client)
  537.     {
  538.       event.u.u.type = XvEventBase + XvVideoNotify;
  539.       event.u.u.sequenceNumber = pn->client->sequence;
  540.       event.u.videoNotify.time = currentTime.milliseconds;
  541.       event.u.videoNotify.drawable = pDraw->id;
  542.       event.u.videoNotify.port = pPort->id;
  543.       event.u.videoNotify.reason = reason;
  544.       (void) TryClientEvents(pn->client, &event, 1, NoEventMask,
  545.                  NoEventMask, NullGrab);
  546.     }
  547.       pn = pn->next;
  548.     }
  549.  
  550.   return Success;
  551.  
  552. }
  553.  
  554.  
  555. int
  556. XvdiSendPortNotify(pPort, attribute, value)
  557.  
  558. XvPortPtr pPort;
  559. Atom attribute;
  560. INT32 value;
  561.  
  562. {
  563.   xvEvent event;
  564.   XvPortNotifyPtr pn;
  565.  
  566.   pn = pPort->pNotify;
  567.  
  568.   while (pn) 
  569.     {
  570.       if (pn->client)
  571.     {
  572.       event.u.u.type = XvEventBase + XvPortNotify;
  573.       event.u.u.sequenceNumber = pn->client->sequence;
  574.       event.u.portNotify.time = currentTime.milliseconds;
  575.       event.u.portNotify.port = pPort->id;
  576.       event.u.portNotify.attribute = attribute;
  577.       event.u.portNotify.value = value;
  578.       (void) TryClientEvents(pn->client, &event, 1, NoEventMask,
  579.                  NoEventMask, NullGrab);
  580.     }
  581.       pn = pn->next;
  582.     }
  583.  
  584.   return Success;
  585.  
  586. }
  587.  
  588. int
  589. XvdiPutVideo(client, pDraw, pPort, pGC, vid_x, vid_y, vid_w, vid_h,
  590.          drw_x, drw_y, drw_w, drw_h)
  591.  
  592. ClientPtr client;
  593. DrawablePtr pDraw;
  594. XvPortPtr pPort;
  595. GCPtr pGC;
  596. INT16 vid_x, vid_y, drw_x, drw_y;
  597. CARD16 vid_w, vid_h, drw_w, drw_h;
  598.  
  599. {
  600.   int status, id;
  601.   DrawablePtr pOldDraw;
  602.  
  603.   /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
  604.  
  605.   UpdateCurrentTime();
  606.  
  607.   /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
  608.      INFORM CLIENT OF ITS FAILURE */
  609.  
  610.   if (pPort->grab.client && (pPort->grab.client != client))
  611.     {
  612.       XvdiSendVideoNotify(pPort, pDraw, XvBusy);
  613.       return Success;
  614.     }
  615.  
  616.   /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
  617.      EVENTS TO ANY CLIENTS WHO WANT THEM */
  618.  
  619.   pOldDraw = pPort->pDraw;
  620.   if ((pOldDraw) && (pOldDraw != pDraw))
  621.     {
  622.       XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
  623.     }
  624.  
  625.   status = (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC, 
  626.                        vid_x, vid_y, vid_w, vid_h, 
  627.                        drw_x, drw_y, drw_w, drw_h);
  628.  
  629.   if ((pPort->pDraw) && (pOldDraw != pDraw))
  630.     {
  631.       pPort->client = client;
  632.       XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
  633.     }
  634.  
  635.   pPort->time = currentTime;
  636.  
  637.   return (Success);
  638.  
  639. }
  640.  
  641. int
  642. XvdiPutStill(client, pDraw, pPort, pGC, vid_x, vid_y, vid_w, vid_h,
  643.          drw_x, drw_y, drw_w, drw_h)
  644.  
  645. ClientPtr client;
  646. DrawablePtr pDraw;
  647. XvPortPtr pPort;
  648. GCPtr pGC;
  649. INT16 vid_x, vid_y, drw_x, drw_y;
  650. CARD16 vid_w, vid_h, drw_w, drw_h;
  651.  
  652. {
  653.   int status, id;
  654.  
  655.   /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
  656.  
  657.   UpdateCurrentTime();
  658.  
  659.   /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
  660.      INFORM CLIENT OF ITS FAILURE */
  661.  
  662.   if (pPort->grab.client && (pPort->grab.client != client))
  663.     {
  664.       XvdiSendVideoNotify(pPort, pDraw, XvBusy);
  665.       return Success;
  666.     }
  667.  
  668.   pPort->time = currentTime;
  669.  
  670.   status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC, 
  671.                        vid_x, vid_y, vid_w, vid_h, 
  672.                        drw_x, drw_y, drw_w, drw_h);
  673.  
  674.   return status;
  675.  
  676. }
  677. int
  678. XvdiGetVideo(client, pDraw, pPort, pGC, vid_x, vid_y, vid_w, vid_h,
  679.          drw_x, drw_y, drw_w, drw_h)
  680.  
  681. ClientPtr client;
  682. DrawablePtr pDraw;
  683. XvPortPtr pPort;
  684. GCPtr pGC;
  685. INT16 vid_x, vid_y, drw_x, drw_y;
  686. CARD16 vid_w, vid_h, drw_w, drw_h;
  687.  
  688. {
  689.   int status, id;
  690.   DrawablePtr pOldDraw;
  691.  
  692.   /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
  693.  
  694.   UpdateCurrentTime();
  695.  
  696.   /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
  697.      INFORM CLIENT OF ITS FAILURE */
  698.  
  699.   if (pPort->grab.client && (pPort->grab.client != client))
  700.     {
  701.       XvdiSendVideoNotify(pPort, pDraw, XvBusy);
  702.       return Success;
  703.     }
  704.  
  705.   /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED
  706.      EVENTS TO ANY CLIENTS WHO WANT THEM */
  707.  
  708.   pOldDraw = pPort->pDraw;
  709.   if ((pOldDraw) && (pOldDraw != pDraw))
  710.     {
  711.       XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
  712.     }
  713.  
  714.   status = (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC,
  715.                        vid_x, vid_y, vid_w, vid_h, 
  716.                        drw_x, drw_y, drw_w, drw_h);
  717.  
  718.   if ((pPort->pDraw) && (pOldDraw != pDraw))
  719.     {
  720.       pPort->client = client;
  721.       XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted);
  722.     }
  723.  
  724.   pPort->time = currentTime;
  725.  
  726.   return (Success);
  727.  
  728. }
  729.  
  730. int
  731. XvdiGetStill(client, pDraw, pPort, pGC, vid_x, vid_y, vid_w, vid_h,
  732.          drw_x, drw_y, drw_w, drw_h)
  733.  
  734. ClientPtr client;
  735. DrawablePtr pDraw;
  736. XvPortPtr pPort;
  737. GCPtr pGC;
  738. INT16 vid_x, vid_y, drw_x, drw_y;
  739. CARD16 vid_w, vid_h, drw_w, drw_h;
  740.  
  741. {
  742.   int status, id;
  743.  
  744.   /* UPDATE TIME VARIABLES FOR USE IN EVENTS */
  745.  
  746.   UpdateCurrentTime();
  747.  
  748.   /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
  749.      INFORM CLIENT OF ITS FAILURE */
  750.  
  751.   if (pPort->grab.client && (pPort->grab.client != client))
  752.     {
  753.       XvdiSendVideoNotify(pPort, pDraw, XvBusy);
  754.       return Success;
  755.     }
  756.  
  757.   status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC, 
  758.                        vid_x, vid_y, vid_w, vid_h, 
  759.                        drw_x, drw_y, drw_w, drw_h);
  760.  
  761.   pPort->time = currentTime;
  762.  
  763.   return status;
  764.  
  765. }
  766.  
  767. int
  768. XvdiGrabPort(client, pPort, ctime, p_result)
  769.  
  770. ClientPtr client;
  771. XvPortPtr pPort;
  772. Time ctime;
  773. int *p_result;
  774.  
  775. {
  776.   unsigned long id;
  777.   TimeStamp time;
  778.  
  779.   UpdateCurrentTime();
  780.   time = ClientTimeToServerTime(ctime);
  781.  
  782.   if (pPort->grab.client && (client != pPort->grab.client))
  783.     {
  784.       *p_result = XvAlreadyGrabbed;
  785.       return Success;
  786.     }
  787.  
  788.   if ((CompareTimeStamps(time, currentTime) == LATER) ||
  789.       (CompareTimeStamps(time, pPort->time) == EARLIER))
  790.     {
  791.       *p_result = XvInvalidTime;
  792.       return Success;
  793.     }
  794.  
  795.   if (client == pPort->grab.client)
  796.     {
  797.       *p_result = Success;
  798.       return Success;
  799.     }
  800.  
  801.   id = FakeClientID(client->index);
  802.  
  803.   if (!AddResource(id, XvRTGrab, &pPort->grab))
  804.     {
  805.       return BadAlloc;
  806.     }
  807.  
  808.   /* IF THERE IS ACTIVE VIDEO THEN STOP IT */
  809.  
  810.   if ((pPort->pDraw) && (client != pPort->client))
  811.     {
  812.       XVCALL(diStopVideo)((ClientPtr)NULL, pPort, pPort->pDraw);
  813.     }
  814.  
  815.   pPort->grab.client = client;
  816.   pPort->grab.id = id;
  817.  
  818.   pPort->time = currentTime;
  819.  
  820.   *p_result = Success;
  821.  
  822.   return Success;
  823.  
  824. }
  825.  
  826. int
  827. XvdiUngrabPort(client, pPort, ctime)
  828.  
  829. ClientPtr client;
  830. XvPortPtr pPort;
  831. Time ctime;
  832.  
  833. {
  834.   TimeStamp time;
  835.  
  836.   UpdateCurrentTime();
  837.   time = ClientTimeToServerTime(ctime);
  838.  
  839.   if ((!pPort->grab.client) || (client != pPort->grab.client))
  840.     {
  841.       return Success;
  842.     }
  843.  
  844.   if ((CompareTimeStamps(time, currentTime) == LATER) ||
  845.       (CompareTimeStamps(time, pPort->time) == EARLIER))
  846.     {
  847.       return Success;
  848.     }
  849.  
  850.   /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */
  851.  
  852.   FreeResource(pPort->grab.id, XvRTGrab);
  853.   pPort->grab.client = (ClientPtr)NULL;
  854.  
  855.   pPort->time = currentTime;
  856.  
  857.   return Success;
  858.  
  859. }
  860.  
  861.  
  862. int
  863. XvdiSelectVideoNotify(client, pDraw, onoff)
  864.  
  865. ClientPtr client;
  866. DrawablePtr pDraw;
  867. BOOL onoff;
  868.  
  869. {
  870.   register int ii;
  871.   int id;
  872.   XvVideoNotifyPtr pn,tpn,fpn;
  873.  
  874.   /* FIND VideoNotify LIST */
  875.  
  876.   pn = (XvVideoNotifyPtr)LookupIDByType(pDraw->id, XvRTVideoNotifyList);
  877.  
  878.   /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */
  879.  
  880.   if (!onoff && !pn) return Success;
  881.  
  882.   /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST
  883.      WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */
  884.  
  885.   if (!pn) 
  886.     {
  887.       if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec))))
  888.     return BadAlloc;
  889.       tpn->next = (XvVideoNotifyPtr)NULL;
  890.       if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn))
  891.     {
  892.       xfree(tpn);
  893.       return BadAlloc;
  894.     }
  895.     }
  896.   else
  897.     {
  898.       /* LOOK TO SEE IF ENTRY ALREADY EXISTS */
  899.  
  900.       fpn = (XvVideoNotifyPtr)NULL;
  901.       tpn = pn;
  902.       while (tpn)
  903.     {
  904.       if (tpn->client == client) 
  905.         {
  906.           if (!onoff) tpn->client = (ClientPtr)NULL;
  907.           return Success;
  908.         }
  909.       if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */
  910.       tpn = tpn->next;
  911.     }
  912.  
  913.       /* IF TUNNING OFF, THEN JUST RETURN */
  914.  
  915.       if (!onoff) return Success;
  916.  
  917.       /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */
  918.  
  919.       if (fpn)
  920.     {
  921.       tpn = fpn;
  922.     }
  923.       else
  924.     {
  925.       if (!(tpn = (XvVideoNotifyPtr)xalloc(sizeof(XvVideoNotifyRec))))
  926.         return BadAlloc;
  927.       tpn->next = pn->next;
  928.       pn->next = tpn;
  929.     }
  930.     }
  931.  
  932.   /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */
  933.   /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */
  934.  
  935.   tpn->client = (ClientPtr)NULL;
  936.   tpn->id = FakeClientID(client->index);
  937.   AddResource(tpn->id, XvRTVideoNotify, tpn);
  938.  
  939.   tpn->client = client;
  940.   return Success;
  941.  
  942. }
  943.  
  944. int
  945. XvdiSelectPortNotify(client, pPort, onoff)
  946.  
  947. ClientPtr client;
  948. XvPortPtr pPort;
  949. BOOL onoff;
  950.  
  951. {
  952.   register int ii;
  953.   int id;
  954.   XvPortNotifyPtr pn,tpn;
  955.  
  956.   /* SEE IF CLIENT IS ALREADY IN LIST */
  957.  
  958.   tpn = (XvPortNotifyPtr)NULL;
  959.   pn = pPort->pNotify;
  960.   while (pn)
  961.     {
  962.       if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */
  963.       if (pn->client == client) break;
  964.       pn = pn->next;
  965.     }
  966.  
  967.   /* IS THE CLIENT ALREADY ON THE LIST? */
  968.  
  969.   if (pn)
  970.     {
  971.       /* REMOVE IT? */
  972.  
  973.       if (!onoff)
  974.     {
  975.       pn->client = (ClientPtr)NULL;
  976.       FreeResource(pn->id, XvRTPortNotify);
  977.     }
  978.  
  979.       return Success;
  980.     }
  981.  
  982.   /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE 
  983.      CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */
  984.  
  985.   if (!tpn)
  986.     {
  987.       if (!(tpn = (XvPortNotifyPtr)xalloc(sizeof(XvPortNotifyRec))))
  988.     return BadAlloc;
  989.       tpn->next = pPort->pNotify;
  990.       pPort->pNotify = tpn;
  991.     }
  992.  
  993.   tpn->client = client;
  994.   tpn->id = FakeClientID(client->index);
  995.   AddResource(tpn->id, XvRTPortNotify, tpn);
  996.  
  997.   return Success;
  998.  
  999. }
  1000.  
  1001. int
  1002. XvdiStopVideo(client, pPort, pDraw)
  1003.  
  1004. ClientPtr client;
  1005. XvPortPtr pPort;
  1006. DrawablePtr pDraw;
  1007.  
  1008. {
  1009.   int status;
  1010.  
  1011.   /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
  1012.  
  1013.   if (!pPort->pDraw || (pPort->pDraw != pDraw)) 
  1014.     {
  1015.       XvdiSendVideoNotify(pPort, pDraw, XvStopped);
  1016.       return Success;
  1017.     }
  1018.  
  1019.   /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN
  1020.      INFORM CLIENT OF ITS FAILURE */
  1021.  
  1022.   if ((client) && (pPort->grab.client) && (pPort->grab.client != client))
  1023.     {
  1024.       XvdiSendVideoNotify(pPort, pDraw, XvBusy);
  1025.       return Success;
  1026.     }
  1027.  
  1028.   XvdiSendVideoNotify(pPort, pDraw, XvStopped);
  1029.  
  1030.   status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw);
  1031.  
  1032.   pPort->pDraw = (DrawablePtr)NULL;
  1033.   pPort->client = (ClientPtr)client;
  1034.   pPort->time = currentTime;
  1035.  
  1036.   return status;
  1037.  
  1038. }
  1039.  
  1040. int
  1041. XvdiPreemptVideo(client, pPort, pDraw)
  1042.  
  1043. XvPortPtr pPort;
  1044. DrawablePtr pDraw;
  1045.  
  1046. {
  1047.   int status;
  1048.  
  1049.   /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */
  1050.  
  1051.   if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success;
  1052.  
  1053.   XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted);
  1054.  
  1055.   status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw);
  1056.  
  1057.   pPort->pDraw = (DrawablePtr)NULL;
  1058.   pPort->client = (ClientPtr)client;
  1059.   pPort->time = currentTime;
  1060.  
  1061.   return status;
  1062.  
  1063. }
  1064.  
  1065. XvdiMatchPort(pPort, pDraw)
  1066. XvPortPtr pPort;
  1067. DrawablePtr pDraw;
  1068.  
  1069. {
  1070.  
  1071.   XvAdaptorPtr pa;
  1072.   XvFormatPtr pf;
  1073.   int nf;
  1074.  
  1075.   pa = pPort->pAdaptor;
  1076.  
  1077.   if (pa->pScreen != pDraw->pScreen) return BadMatch;
  1078.  
  1079.   nf = pa->nFormats;
  1080.   pf = pa->pFormats;
  1081.  
  1082.   while (nf--)
  1083.     {
  1084.       if ((pf->depth == pDraw->depth) &&
  1085.       ((pDraw->type == DRAWABLE_PIXMAP) || 
  1086.        (wVisual(((WindowPtr)pDraw)) == pf->visual)))
  1087.     return Success;
  1088.       pf++;
  1089.     }
  1090.  
  1091.   return BadMatch;
  1092.  
  1093. }
  1094.  
  1095. int
  1096. XvdiSetPortAttribute(client, pPort, attribute, value)
  1097. ClientPtr client;
  1098. XvPortPtr pPort;
  1099. Atom attribute;
  1100. INT32 value;
  1101.  
  1102. {
  1103.  
  1104.   return 
  1105.     (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value);
  1106.  
  1107. }
  1108.  
  1109. int
  1110. XvdiGetPortAttribute(client, pPort, attribute, p_value)
  1111. ClientPtr client;
  1112. XvPortPtr pPort;
  1113. Atom attribute;
  1114. INT32 *p_value;
  1115.  
  1116. {
  1117.  
  1118.   return 
  1119.     (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value);
  1120.  
  1121. }
  1122.  
  1123. static void
  1124. WriteSwappedVideoNotifyEvent(from, to)
  1125.  
  1126. xvEvent *from, *to;
  1127.  
  1128. {
  1129.  
  1130.   to->u.u.type = from->u.u.type;
  1131.   to->u.u.detail = from->u.u.detail;
  1132.   cpswaps(from->u.videoNotify.sequenceNumber, 
  1133.       to->u.videoNotify.sequenceNumber);
  1134.   cpswapl(from->u.videoNotify.time, to->u.videoNotify.time);
  1135.   cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable);
  1136.   cpswapl(from->u.videoNotify.port, to->u.videoNotify.port);
  1137.  
  1138. }
  1139.  
  1140. static void
  1141. WriteSwappedPortNotifyEvent(from, to)
  1142.  
  1143. xvEvent *from, *to;
  1144.  
  1145. {
  1146.  
  1147.   to->u.u.type = from->u.u.type;
  1148.   to->u.u.detail = from->u.u.detail;
  1149.   cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber);
  1150.   cpswapl(from->u.portNotify.time, to->u.portNotify.time);
  1151.   cpswapl(from->u.portNotify.port, to->u.portNotify.port);
  1152.   cpswapl(from->u.portNotify.value, to->u.portNotify.value);
  1153.  
  1154. }
  1155.